import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:im_base/im_base.dart';
import 'package:im_base/public/components/avatar_widgets.dart';
import 'package:im_base/public/components/layout_widgets.dart';
import 'package:im_base/public/global/custom_bean.dart';
import 'package:im_base/public/global/global.dart';
import 'package:im_base/public/global/im_keys.dart';
import 'package:im_base/public/pages/preview_photo/view.dart';
import 'package:im_base/public/pages/video_player/view.dart';
import 'package:tencent_im_sdk_plugin/enum/message_elem_type.dart';
import 'package:tencent_im_sdk_plugin/models/v2_tim_message.dart';
import 'package:im_base/public/ext/string_ext.dart';

import '../logic.dart';
import '../state.dart';
import 'audio/view.dart';

///聊天消息 item
class ChatMessage extends StatelessWidget {
  final V2TimMessage message;
  final Key key;

  ///是否能够操作消息
  final bool? canOperation;

  ChatMessage({required this.message, required this.key, this.canOperation})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        getDate(message),
        messageItems(message, canOperation: canOperation ?? true)
      ],
    );
  }
}

///获取时间展示widget
Widget getDate(V2TimMessage message) {
  String? showTime;
  if (Get.isRegistered<ChatLogic>(tag: message.userID ?? message.groupID)) {
    ChatState state =
        Get.find<ChatLogic>(tag: message.userID ?? message.groupID).state;
    showTime = showDate(message.timestamp ?? 0, state.currentTime);
    if (!showTime.isNullEmpty()) {
      state.currentTime = (message.timestamp ?? 1) * 1000;
    }
  } else {
    showTime = showDate(message.timestamp ?? 0, Global.currentTime);
    if (!showTime.isNullEmpty()) {
      Global.currentTime = (message.timestamp ?? 1) * 1000;
    }
  }

  return showTime.isNullEmpty()
      ? Container()
      : Container(
          margin: EdgeInsets.only(top: 8, bottom: 8),
          padding: EdgeInsets.only(left: 4, right: 4, top: 2, bottom: 2),
          decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(2), color: Colors.grey[350]),
          child: Text(
            showTime!,
            style: TextStyle(color: Colors.white, fontSize: 12),
          ),
        );
}

///判断当前消息类型
Widget messageItems(V2TimMessage message, {bool? canOperation}) {
  if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS ||
      message.elemType == MessageElemType.V2TIM_ELEM_TYPE_NONE ||
      message.status == 6) {
    return notifyMessage(notifyMsg(message));
  }
  if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_CUSTOM) {
    return customMessage(message, canOperation: canOperation);
  }
  return message.sender == Global.IDENTIFIER
      ? selfMessage(message, canOperation: canOperation)
      : otherMessage(message);
}

///自定义消息
Widget customMessage(V2TimMessage message, {bool? canOperation}) {
  try {
    String data = (message.customElem?.data ?? '').isEmpty
        ? message.customElem?.extension ?? ''
        : message.customElem?.data ?? '';
    if (!data.contains('\'') && !data.contains('\"')) {
      data = data
          .replaceAll('{', '{"')
          .replaceAll(':', '":"')
          .replaceAll(',', '","')
          .replaceAll('}', '"}')
          .replaceAll(' ', '')
          .trim();
    }
    final bean = CustomBean.fromMap(jsonDecode(data));
    switch (bean.msg) {
      case IMKeys.TYPE_RECOMMEND: //群推荐
      case IMKeys.RECIPE:
        return Global.IDENTIFIER.contains('doc')
            ? selfMessage(message, canOperation: canOperation)
            : otherMessage(message);
      case IMKeys.TYPE_CASE: //病历信息
        return caseView(message, bean);

      default:
        return notifyMessage(customMsg(message.customElem));
    }
  } on Exception catch (e) {
    return notifyMessage(customMsg(message.customElem));
  }
}

///患者病历信息
Widget caseView(V2TimMessage message, CustomBean bean) {
  return Card(
    elevation: 3,
    borderOnForeground: false,
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
    margin: EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 4),
    child: Container(
      padding: EdgeInsets.fromLTRB(16, 12, 16, 6),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              Avatar(
                backgroundImage: message.faceUrl.isNullEmpty()
                    ? null
                    : NetworkImage(message.faceUrl!),
                shape: AvatarShape.circle,
                size: 24,
              ),
              Text(
                bean.userName ?? message.nickName ?? '',
                style: TextStyle(color: Colors.black87, fontSize: 18),
              ).marginOnly(left: 8),
              Text('${bean.getGender()}  ${bean.age}').marginOnly(left: 12)
            ],
          ),
          Text(
            bean.intro ?? '',
            style: TextStyle(color: Colors.grey[800], fontSize: 14),
            softWrap: true,
          ).marginOnly(top: 8),
          Divider(
            color: Colors.grey[300],
          ),
          Align(
            alignment: Alignment.bottomRight,
            child: Text(
              DateTime.fromMillisecondsSinceEpoch(
                      (message.timestamp ?? 0) * 1000)
                  .toString()
                  .replaceAll('.000', ''),
              style: TextStyle(color: Colors.grey, fontSize: 12),
            ),
          )
        ],
      ),
    ),
  );
}

///提示信息 widget
Widget notifyMessage(String message) {
  return message.isNullEmpty()
      ? Container()
      : Container(
          margin: EdgeInsets.only(top: 8, bottom: 8),
          alignment: Alignment.center,
          width: double.infinity,
          child: Text(
            message,
            style: TextStyle(color: Colors.grey, fontSize: 12),
          ),
        );
}

///对方发送消息widget
Widget otherMessage(V2TimMessage message) {
  return Container(
    width: double.infinity,
    margin: EdgeInsets.only(top: 8, left: 16, bottom: 8),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        InkWell(
          highlightColor: Colors.transparent,
          splashColor: Colors.transparent,
          onTap: () {
            ///将对方的头像点击事件抛出
            Get.find<ChatLogic>(tag: message.userID ?? message.groupID)
                .headerClick(
                    message.sender,
                    message.nickName ??
                        message.nameCard ??
                        message.friendRemark ??
                        '未知');
          },
          child: Avatar(
            backgroundImage: message.faceUrl.isNullEmpty()
                ? null
                : NetworkImage(message.faceUrl!),
            shape: AvatarShape.circle,
          ),
        ),
        getMessageBody(message, false)
      ],
    ),
  );
}

///自己发送的消息widget
Widget selfMessage(V2TimMessage message, {bool? canOperation}) {
  return Container(
    width: double.infinity,
    margin: EdgeInsets.only(top: 8, right: 16, bottom: 8),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.end,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        getMessageBody(message, true, canOperation: canOperation),
        Avatar(
          backgroundImage: message.faceUrl.isNullEmpty()
              ? null
              : NetworkImage(message.faceUrl!),
          shape: AvatarShape.circle,
        )
      ],
    ),
  );
}

///根据消息类型获取消息体
Widget getMessageBody(V2TimMessage message, bool isSelf, {bool? canOperation}) {
  return GestureDetector(
    child: Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        isSelf
            ? Container(
                margin: EdgeInsets.only(top: 12, right: 6),
                width: 12,
                height: 12,
                alignment: Alignment.center,
                child: (message.progress ?? 100) < 100
                    ? CircularProgressIndicator(
                        strokeWidth: 2,
                      )
                    : null,
              )
            : Container(),
        getMessage(message, isSelf),
        !isSelf
            ? Container(
                margin: EdgeInsets.only(top: 12, left: 6),
                width: 12,
                height: 12,
                alignment: Alignment.center,
                child: (message.progress ?? 100) < 100
                    ? CircularProgressIndicator(
                        strokeWidth: 2,
                      )
                    : null,
              )
            : Container(),
      ],
    ),
    onTap: () {},
    onLongPress: () {},
    onLongPressStart: (detail) {
      if (canOperation ?? true) {
        Get.find<ChatLogic>(tag: message.userID ?? message.groupID).showPopMenu(
            detail.globalPosition,
            message.msgID ?? '',
            isSelf,
            message.timestamp ?? 0,
            (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_TEXT
                ? message.textElem!.text
                : "")!);
      }
    },
  );
}

///根据消息体展示views
Widget getMessage(V2TimMessage message, bool isSelf) {
  switch (message.elemType) {
    case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
    case MessageElemType.V2TIM_ELEM_TYPE_FACE:
      return getTextWidget(message.textElem!.text ?? "", isSelf);
    case MessageElemType.V2TIM_ELEM_TYPE_IMAGE:
      return getImage(message, isSelf);
    case MessageElemType.V2TIM_ELEM_TYPE_VIDEO:
      return getVideo(message, isSelf);
    case MessageElemType.V2TIM_ELEM_TYPE_SOUND:
      return getAudioWidget(message);
    case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM:
      return getCustomWidget(message);
    default:
      return getTextWidget('不支持的消息类型', isSelf);
  }
}

///视频消息
Widget getVideo(V2TimMessage message, bool isSelf) {
  var video = message.videoElem;
  if (video == null) {
    return getTextWidget('错误的视频格式', isSelf);
  }
  var height = video.snapshotHeight ?? 0;
  var wide = video.snapshotWidth ?? 0;
  var duration = video.duration;
  var videoPath = video.videoPath ?? video.videoUrl;

  ///必须宽高都有值才能计算比例,如果有一个没有值则默认16:9
  double scale = 16 / 9;
  double showWide = 120;
  if (height > 0 && wide > 0) {
    showWide = (height > wide) ? 120 : 180;
    scale = height / wide;
  }

  return HeroWidget(
      tag: message.msgID ?? '',
      child: GestureDetector(
        onTap: () => Get.to(() => VideoPlayerPage(), arguments: {
          'url': video.videoUrl,
          'path': video.videoPath,
          'tag': message.msgID,
          'isNetwork': video.videoUrl != null
        }),
        child: Container(
          padding: EdgeInsets.all(8),
          margin: EdgeInsets.only(top: 8, left: 12, right: 12, bottom: 8),
          width: showWide,
          height: showWide * scale,
          decoration: BoxDecoration(
              color: Colors.black12,
              borderRadius: BorderRadius.circular(12),
              image: DecorationImage(
                  image: (video.snapshotPath == null
                          ? NetworkImage(video.snapshotUrl ?? '')
                          : FileImage(File(video.snapshotPath ?? '')))
                      as ImageProvider)),
          child: Stack(
            children: [
              Align(
                alignment: Alignment.bottomCenter,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      getSize(video.videoSize),
                      style: TextStyle(color: Colors.white, fontSize: 12),
                    ),
                    Text(
                      '${video.duration}s',
                      style: TextStyle(color: Colors.white, fontSize: 12),
                    )
                  ],
                ),
              ),
              Align(
                alignment: Alignment.center,
                child: Icon(
                  Icons.play_circle_outline,
                  color: Colors.white,
                  size: 36,
                ),
              )
            ],
          ),
        ),
      ));
}

///按照对话格式展示自定义的消息内容
Widget getCustomWidget(V2TimMessage message) {
  String data = (message.customElem?.data ?? '').isEmpty
      ? message.customElem?.extension ?? ''
      : message.customElem?.data ?? '';
  if (!data.contains('\'') && !data.contains('\"')) {
    data = data
        .replaceAll('{', '{"')
        .replaceAll(':', '":"')
        .replaceAll(',', '","')
        .replaceAll('}', '"}')
        .replaceAll(' ', '')
        .trim();
  }
  final bean = CustomBean.fromMap(jsonDecode(data));
  bool isSelf = message.sender == Global.IDENTIFIER;
  late Widget child;
  switch (bean.msg) {
    case IMKeys.TYPE_RECOMMEND:

      ///群推荐使用自定义UI
      return groupRecommend(bean, isSelf);
    case IMKeys.RECIPE:

      ///后台发送消息的时候使用的对方账户相互发送,所以这里判断下账号,如果是医生账号,则直接展示
      isSelf = true;
      child = recipeView(message, bean, isSelf);
      break;
    default:
      child = Container();
      break;
  }

  return Container(
    padding: EdgeInsets.fromLTRB(16, 12, 16, 12),
    margin: isSelf
        ? EdgeInsets.only(top: 12, right: 8)
        : EdgeInsets.only(top: 12, left: 8),
    decoration: BoxDecoration(
        color: isSelf ? Colors.green[300] : Colors.white,
        border: Border.all(color: Colors.grey[200]!, width: 0.5),
        borderRadius: isSelf
            ? BorderRadius.only(
                topLeft: Radius.circular(6),
                bottomLeft: Radius.circular(6),
                bottomRight: Radius.circular(24))
            : BorderRadius.only(
                topRight: Radius.circular(6),
                bottomRight: Radius.circular(6),
                bottomLeft: Radius.circular(24))),
    child: child,
  );
}

///群推荐
Widget groupRecommend(CustomBean bean, bool isSelf) {
  return InkWell(
    onTap: () => poseClick(bean),
    splashColor: Colors.transparent,
    highlightColor: Colors.transparent,
    child: Container(
      constraints: BoxConstraints(maxWidth: Get.width * 0.6),
      margin: isSelf
          ? EdgeInsets.only(top: 12, right: 8)
          : EdgeInsets.only(top: 12, left: 8),
      padding: EdgeInsets.all(12),
      decoration: BoxDecoration(
          color: Colors.white,
          border: Border.all(color: Colors.grey[300]!),
          borderRadius: BorderRadius.circular(8)),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(
            '邀请您加入 ${bean.text}',
            style: TextStyle(fontSize: 14, color: Colors.black54),
          ),
          Text(
            '简介:${bean.value.toString().isEmpty ? '无' : bean.value}',
            style: TextStyle(fontSize: 12, color: Colors.grey),
            maxLines: 2,
            overflow: TextOverflow.ellipsis,
          ),
          Text(
            '查看详情>>',
            style: TextStyle(fontSize: 14, color: Colors.blue),
          )
        ],
      ),
    ),
  );
}

Widget recipeView(V2TimMessage message, CustomBean bean, bool isSelf) {
  bean.msgID = message.msgID;
  return InkWell(
    onTap: () => poseClick(bean),
    child: Container(
      decoration:
          BoxDecoration(color: isSelf ? Colors.green[300] : Colors.white),
      constraints: BoxConstraints(maxWidth: Get.width * 0.6),
      child: Column(
        children: [
          Text.rich(
            TextSpan(children: [
              TextSpan(
                  text: isSelf ? '您为患者开具了处方笺,' : '医生为您开具处方笺,请',
                  style: TextStyle(fontSize: 14, color: Colors.black87)),
              TextSpan(
                  text: '点击查看处方详情',
                  style: TextStyle(fontSize: 14, color: Colors.blue[600])),
              TextSpan(
                  text: isSelf ? ',如有错误,可点击作废。' : ',如有需求,可点击进行支付。',
                  style: TextStyle(fontSize: 14, color: Colors.black87))
            ]),
            softWrap: true,
            maxLines: 2,
          ),
          isSelf
              ? Container()
              : Container(
                  margin: EdgeInsets.only(top: 6),
                  decoration: BoxDecoration(
                      border:
                          Border(bottom: BorderSide(color: Colors.grey[200]!))),
                )
        ],
      ),
    ),
  );
}

///语音消息展示
Widget getAudioWidget(V2TimMessage message) {
  return AudioWidget(
      message.msgID!,
      message.soundElem!.path!,
      message.soundElem!.url ?? '',
      message.soundElem!.duration!,
      message.sender == Global.IDENTIFIER,
      message.userID);
}

///带有聊天框的消息类型
Widget getTextWidget(String message, bool isSelf) {
  return Container(
    padding: EdgeInsets.fromLTRB(16, 12, 16, 12),
    margin: isSelf
        ? EdgeInsets.only(top: 12, right: 8)
        : EdgeInsets.only(top: 12, left: 8),
    decoration: BoxDecoration(
        color: isSelf ? Colors.green[300] : Colors.white,
        border: Border.all(color: Colors.grey[200]!, width: 0.5),
        borderRadius: isSelf
            ? BorderRadius.only(
                topLeft: Radius.circular(6),
                bottomLeft: Radius.circular(6),
                bottomRight: Radius.circular(24))
            : BorderRadius.only(
                topRight: Radius.circular(6),
                bottomRight: Radius.circular(6),
                bottomLeft: Radius.circular(24))),
    constraints: BoxConstraints(
        minHeight: 45, maxWidth: Get.width * 0.6, maxHeight: double.infinity),
    child: getText(message),
  );
}

///图片展示,为了更好的体验,优先加载本地的图片,
///如果本地没有该图片,则使用缩略图
Widget getImage(V2TimMessage message, bool isSelf) {
  var image = message.imageElem!.imageList;
  double scale = 16 / 9;
  var imageLocal =
      message.imageElem!.path == null ? null : File(message.imageElem!.path!);
  if (image == null || image.length == 1||image.first?.url==null) {
    ///如果是imageList为空，或者只有一个，说明是新上传的图片，此时返回本地图片
    return Container(
        margin: EdgeInsets.only(top: 8, left: 12, right: 12, bottom: 8),
        width: 120,
        height: 120 * scale,
        child: PhysicalModel(
          color: Colors.transparent,
          clipBehavior: Clip.antiAlias,
          borderRadius: BorderRadius.circular(12),
          child: imageLocal == null
              ? Container()
              : Image(
                  image: FileImage(imageLocal),
                  errorBuilder: (context, aa, bb) {
                    return Container();
                  },
                ),
        ));
  }
  var smallImage = image.where((element) =>Platform.isAndroid? element?.type == 0:element?.type==2).first;
  var bigImage = image.where((element) => Platform.isAndroid?element?.type == 2:element?.type==4).first;

  if (smallImage == null) {
    smallImage = image.where((element) => element?.type == 1).first;
  }

  if (bigImage == null) {
    bigImage = image.where((element) => element?.type == 1).first;
  }

  if (smallImage != null && (smallImage.url ?? '').isNotEmpty) {
    ///如果有缩略图,说明已经上传成功,可以获取到图片宽高值
    scale = smallImage.height! / smallImage.width!;
  }

  return HeroWidget(
    tag: message.msgID!,
    child: GestureDetector(
      onTap: () {
        if (isSelf) {
          ///如果是自己发送的图片则查看单个图片即可
          Get.to(() => PreviewPhotoPage(), arguments: {
            'imgUrl': bigImage?.url ?? '',
            'msgId': message.msgID,
            'path': message.imageElem!.path
          });
        } else {
          ///如果是对方发送的消息,则查看当前加载的消息列表中的图片列表
          Get.find<ChatLogic>(tag: message.userID ?? message.groupID)
              .checkPhotoList(bigImage?.url ?? '');
        }
      },
      child: Container(
          margin: EdgeInsets.only(top: 8, left: 12, right: 12, bottom: 8),
          width: 120,
          height: 120 * scale,
          child: PhysicalModel(
            color: Colors.transparent,
            clipBehavior: Clip.antiAlias,
            borderRadius: BorderRadius.circular(12),
            child: imageLocal == null
                ? Image.network(
                    smallImage?.url ?? "",
                    fit: BoxFit.fill,
                  )
                : Image(
                    image: FileImage(imageLocal),
                    errorBuilder: (context, aa, bb) {
                      return Image.network(smallImage?.url ?? "");
                    },
                  ),
          )),
    ),
  );
}

///因为emoji也是text类型,所以这里需要做对应的判断
Widget getText(String text) {
  String regex = "\\[(\\S+?)\\]";
  if (RegExp(regex).hasMatch(text)) {
    final group = RegExp(regex).allMatches(text);
    List<InlineSpan> spans = List.empty(growable: true);
    int start = 0; //记录当前emoji起始位置
    group.forEach((element) {
      final subText = text.substring(start, element.start);
      start = element.end;
      if (!subText.isNullEmpty()) {
        spans.add(TextSpan(
            text: subText,
            style: TextStyle(color: Colors.black87, fontSize: 16)));
      }
      spans.add(WidgetSpan(
          child: Image.asset(
        '${Global.EMOJI_PATH}${element.group(0)}@2x.png',
        width: 20,
        height: 20,
      )));
    });
    return Text.rich(TextSpan(children: spans));
  } else {
    return Text(
      text,
      style: TextStyle(color: Colors.black87, fontSize: 16),
    );
  }
}

///抛出点击事件
void poseClick(CustomBean? bean) {
  writeIMData(IMKeys.customMessageClick, bean);
}
